package com.lfy.modules.safety.statistics.pv;

import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.lfy.domain.anno.Describe;
import com.lfy.modules.safety.domain.BlogPvStatistics;
import com.lfy.modules.safety.domain.BlogUvStatistics;
import com.lfy.modules.safety.mapper.BlogPvStatisticsMapper;
import lombok.extern.slf4j.Slf4j;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

import java.sql.SQLException;
import java.time.LocalDate;
import java.time.temporal.ChronoField;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.LongAdder;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author lvfeiyang
 */
@Describe("pv缓存持久化任务")
@Slf4j
public class PvCache implements Job {
    private static final BlogPvStatisticsMapper BLOG_PV_STATISTICS_MAPPER;
    static {
        BLOG_PV_STATISTICS_MAPPER = SpringUtil.getBean(BlogPvStatisticsMapper.class);
    }
    private static final Cache<LocalDate, LongAdder> PV_CACHE = Caffeine.newBuilder()
            .initialCapacity(16)
            .expireAfterWrite(2, TimeUnit.DAYS)
            .maximumSize(10_000)
            .build();

    public static void put() {
      Optional.ofNullable( PV_CACHE.get(LocalDate.now(),(v)->new LongAdder())).ifPresent(LongAdder::increment);
    }

    public static BlogPvStatistics getNowDayPv() {
        LocalDate now = LocalDate.now();
        //今天
        BlogPvStatistics blogPvStatistics = new BlogPvStatistics();
        LongAdder longAdder = PV_CACHE.get(now, (v) -> new LongAdder());
        assert longAdder != null;
        blogPvStatistics.setNum(longAdder.sum());
        blogPvStatistics.setCreateTime(now.toString());
        return blogPvStatistics;
    }
    public static List<BlogPvStatistics> getSevenDaysPv() {
            LocalDate now = LocalDate.now();
            //今天
        BlogPvStatistics nowDayPv = getNowDayPv();
        //前六天
        List<BlogPvStatistics> blogPvStatisticsBySixDays = BLOG_PV_STATISTICS_MAPPER.selectList(new LambdaQueryWrapper<BlogPvStatistics>()
                .between(BlogPvStatistics::getCreateTime, now.minusDays(7), now.minusDays(1)));
        blogPvStatisticsBySixDays.add(nowDayPv);
        List<BlogPvStatistics> blogPvStatistics = buidResult();
        for (BlogPvStatistics blogPvStatistic : blogPvStatistics) {
            for (BlogPvStatistics blogPvStatisticsBySixDay : blogPvStatisticsBySixDays) {
                if (blogPvStatisticsBySixDay.getCreateTime().equals(blogPvStatistic.getCreateTime())) {
                    blogPvStatistic.setNum(blogPvStatisticsBySixDay.getNum());
                }
            }
        }
        return blogPvStatistics;
    }
    private static List<BlogPvStatistics> buidResult(){
        return Stream.iterate(0, i -> ++i).limit(7).map(item -> {
            BlogPvStatistics blogPvStatistics = new BlogPvStatistics();
            blogPvStatistics.setNum(0L);
            blogPvStatistics.setCreateTime(LocalDate.now().minusDays(item).toString());
            return blogPvStatistics;
        }).sorted(Comparator.comparing(BlogPvStatistics::getCreateTime)).collect(Collectors.toList());
    }
    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        BlogPvStatistics nowDayPv = getNowDayPv();
        boolean flag = false;
        try{
            BLOG_PV_STATISTICS_MAPPER.insert(nowDayPv);
            flag = true;
        }catch (Exception e){
            log.error("pv统计数据插入失败");
        }
        //防止调度器重启立即执行一次，导致数据重复插入
        if(!flag){
            try {
                BLOG_PV_STATISTICS_MAPPER.update(nowDayPv,new LambdaQueryWrapper<BlogPvStatistics>().eq(BlogPvStatistics::getCreateTime,nowDayPv.getCreateTime()));
                log.info("pv补偿数据更新成功");
            }catch (Exception e){
                log.error("pv补偿数据更新失败");
            }

        }
    }


}
